#!/usr/bin/python

#
# Copyright (c) 2011-2012 Johann Hanne
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#

import sys
from optparse import OptionParser, OptionValueError
import re
from omf.OMFObject import OMFObject
from omf.LinkerOutput import LinkerOutput

parser = OptionParser()
parser.add_option("-e", "--extendedrealmode", action="store_true", dest="extendedrealmode", default=False,
                  help="enable extended real mode addressing")
parser.add_option("-s", "--startaddress", dest="startaddress", default=None,
                  help="start address segment")
parser.add_option("-o", "--output", dest="output", default="output.bin",
                  help="output file name")
parser.add_option("-m", "--map", dest="mapoutput", default=None,
                  help="map file name")
parser.add_option("-d", "--define", dest="define", action="append", type="string", default=None,
                  help="manually define a symbol")

(options, args) = parser.parse_args()

if not options.extendedrealmode:
    raise OptionValueError("Only extended real mode is supported, so you must use the -e option")

if options.startaddress is None:
    raise OptionValueError("Start address is required (use -s option)")

nums = options.startaddress.split(":")
if len(nums) == 1:
    try:
        segment = int(nums[0], 0)
    except ValueError:
        raise OptionValueError("Invalid start address")
    offset = 0
elif len(nums) == 2:
    try:
        segment = int(nums[0], 0)
        offset = int(nums[1], 0)
    except ValueError:
        raise OptionValueError("Invalid start address")
else:
    raise OptionValueError("Invalid start address")

objlist = []

for fname in args:
    objlist.append(OMFObject(fname))

definitions = {}
if options.define is not None:
    for d in options.define:
        m = re.match("^([^=]+)=([0-9a-fA-F]{4}):([0-9a-fA-F]{4})$", d)
        if m is None:
            raise OptionValueError("Invalid define option: '{0}'".format(d))
        definitions[m.group(1)] = (int(m.group(2), 16), int(m.group(3), 16))

out = LinkerOutput(options.output, options.mapoutput, segment, offset, definitions)

for obj in objlist:
    obj.process(out)

out.check_for_duplicate_names()
out.fixup()
out.write_map()
out.write()

